import {Line} from "./Line";
import {EventCanvas} from "@/utils/EventCanvas";
import {BaseCanvas} from "@/utils/BaseCanvas";
import {InterfaceShape, Shape} from "@/utils/Shape";
import {getShapeClass, ShapeTypeKey} from "@/utils/ShapeTypes";
import {CanvasImage} from "@/utils/Image";
import {InterfaceDragShape} from "@/utils/DragShape";

export type AndShape = InterfaceShape & InterfaceDragShape

export class Drawing extends BaseCanvas {

  // 是否开始画图
  beginPath: boolean;
  // 是否允许画图
  draw: boolean;
  currentShape: Shape | null;
  eventCanvas: EventCanvas;
  shape: typeof Shape;
  // 当前点击的图形id
  activeShapeId: string
  draggingShape: InterfaceDragShape | null

  constructor(canvas: HTMLCanvasElement) {
    super(canvas, canvas.width, canvas.height)

    this.initListener()
    this.currentShape = null
    this.beginPath = false
    this.draw = true
    this.eventCanvas = new EventCanvas(canvas.width, canvas.height)
    this.shape = Line
    this.activeShapeId = ''
    this.draggingShape = null
  }

  initListener() {
    const mousedown = this.mousedown.bind(this)
    const mousemove = this.mousemove.bind(this)
    const mouseup = this.mouseup.bind(this)

    this.canvas.addEventListener('mousedown', mousedown)
    this.canvas.addEventListener('mousemove', mousemove)
    this.canvas.addEventListener('mouseup', mouseup)
    this.canvas.addEventListener('click', this.click.bind(this))
    this.canvas.addEventListener('touchstart', mousedown)
    this.canvas.addEventListener('touchmove', mousemove)
    this.canvas.addEventListener('touchend', mouseup)
    const input = document.createElement('input')
    input.addEventListener('input', function () {

    })

    window.addEventListener('resize', this.resize.bind(this))
  }

  mousedown(event: TouchEvent | MouseEvent) {
    event.preventDefault()
    event.stopPropagation()
    let event_ = this.getEventPoint(event)
    if (this.draw) {
      this.beginPath = true
      this.currentShape = new this.shape(this.ctx, event_.x, event_.y)
    } else {
      const e = this.eventCanvas.click(event_ as MouseEvent)

      if (e) {
        console.log(e)
        const {shape} = e
        this.draggingShape = shape
        const drag = shape.dragStart(event_.x, event_.y)
        if (drag) {
          console.log('拖拽开始.....')
        }
      }
    }
  }

  mousemove(event: TouchEvent | MouseEvent) {
    event.preventDefault()
    event.stopPropagation()
    let event_ = this.getEventPoint(event)
    if (this.draw) {
      if (this.beginPath) {
        this.currentShape?.drawMove(event_.x, event_.y)
      }
    } else {
      const drag = this.draggingShape?.dragging(event_.x, event_.y)
      if (drag) {
        console.log('拖拽过程，重新绘制.....')
        this.reDraw()
        this.eventCanvas.reDraw()
      }
    }
  }

  mouseup(event: TouchEvent | MouseEvent) {
    event.preventDefault()
    event.stopPropagation()
    let event_ = this.getEventPoint(event)
    if (this.draw) {
      if (this.currentShape) {
        const shape = this.currentShape.drawEnd(event_.x, event_.y)

        if (shape) {
          this.shapes.push(this.currentShape)
          this.eventCanvas.pushShape(this.currentShape)

          // 完成一条线之后，恢复区数据会被清空
          this.resetRevocationLines()
        }

        this.beginPath = false
        this.currentShape = null
      }
    } else {
      if (this.draggingShape) {
        this.draggingShape.dragEnd(event_.x, event_.y)
        console.log('拖拽结束.....')
        this.draggingShape = null
      }
    }
  }

  resize() {

  }

  click(event: MouseEvent) {
    if (!this.draw) {
      const e = this.eventCanvas.click(event)
      if (e) {
        this.activeShapeId = e.shapeId
        this.reDraw()
      } else if (this.activeShapeId) {
        this.activeShapeId = ''
        this.reDraw()
      }

    }
  }

  async playback() {
    this.activeShapeId = ''
    this.clearRect()

    if (this.shapes.length) {
      for (const shape of this.shapes) {
        await shape.playback()
      }
    }
  }

  reDraw() {
    this.clearRect()
    if (this.shapes.length) {
      for (const shape of this.shapes) {
        shape.draw(this.activeShapeId)
      }
    }
  }

  clearDraw() {
    this.shapes = []
    this.clearRect()
    this.eventCanvas.clearDraw()
  }

  stopDraw() {
    this.draw = false
  }

  startDraw() {
    this.draw = true
    this.activeShapeId = ''
  }

  setStrokeColor(color: string) {
    if (this.ctx) {
      this.ctx.strokeStyle = color
    }
  }

  setLineWidth(lineWidth: number) {
    if (this.ctx) {
      this.ctx.lineWidth = lineWidth
    }
  }

  getEventPoint(event: TouchEvent | MouseEvent): { x: number, y: number } {
    if (event instanceof TouchEvent) {
      const [{clientX, clientY}] = Array.from(event.touches)
      return {
        x: clientX,
        y: clientY,
      }
    }
    return event
  }

  appendImage(file: File) {
    new CanvasImage(this.ctx, file, shape => {
      this.shapes.push(shape)
      this.eventCanvas.pushShape(shape)
    })
  }

  resetRevocationLines() {
    if (this.revocationShapes.length) {
      this.revocationShapes = []
    }

  }

  setShape(type: ShapeTypeKey) {
    this.shape = getShapeClass(type)
  }
}
